#ifndef TCPCONNECTION_H
#define TCPCONNECTION_H

#include <QString>
#include <QStringList>
#include <QSharedPointer>
#include <string>
#include <QThread>
#include <QThreadPool>
#include <QQueue>
#include <QMutex>
#include <QWaitCondition>
#include <QTcpSocket>
#include <QSslSocket>
#include <QHostAddress>
#include <QUrl>
#include <QList>
#include <QAtomicInt>
#include <QtEndian>
#include <QTimer>

//#include "concurrentqueue.h"
#include "payload.h"
#include "communicationexception.h"
#include "connectionconfig.h"
#include "noncopyable.h"
#include "wireformat.h"
#include "connection.h"
#include "qslog.h"
#include "utils.h"

namespace apollo
{
	namespace core
	{
		class TcpConnection : public Connection
		{
			Q_OBJECT

		public:
			TcpConnection(QSharedPointer<ConnectionConfig> config, 
				QSharedPointer<WireFormat> format = QSharedPointer<WireFormat>(new WireFormat), QObject *parent = NULL);
			virtual ~TcpConnection() throw();
			//inline ConcurrentQueue<PayloadPtr>& getQueue() 	{return queue;}
			QString& getConnectionName() { return config->connectionName;}


			virtual PayloadPtr connect(PayloadPtr loginRequest);
			virtual PayloadPtr reconnect(PayloadPtr loginRequest);
			virtual void disconnect();
			virtual void write(PayloadPtr payload);
			virtual bool isReady() const;
			virtual const SessionState& getState() {return state;}
			
			protected slots:
				void onReadyRead();
				void onConnected();
				void onError(QAbstractSocket::SocketError error);
				void onDisconnected();
				//void loginTimeout();
		private:
			void handleError(const QString &ip, const int port, const QAbstractSocket::SocketError error);
			const ConnectionConfig::UrlConfig* selectUrl(QList<ConnectionConfig::UrlConfig* > *failedUrls) const;
			//void login();
			//void processLogin(PayloadPtr loginResponse);
		private:
			QSharedPointer<ConnectionConfig> config;
			QSharedPointer<QTcpSocket> socket;
			//QSharedPointer<ConnectionReader> reader;
			QSharedPointer<WireFormat> format;

			//ConcurrentQueue<PayloadPtr> queue;
			//QAtomicInt messageId;

			WireFormat::ReadingContext readingCtx;

			SessionState state;
			//QString sessionId;

		};
	}}
#endif // TCPCONNECTION_H
